package com.java.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.java.enums.LendStatusEnum;
import com.java.enums.TransTypeEnum;
import com.java.exceptioin.Assert;
import com.java.hfb.FormHelper;
import com.java.hfb.HfbConst;
import com.java.hfb.RequestHelper;
import com.java.mapper.LendMapper;
import com.java.mapper.UserAccountMapper;
import com.java.mapper.UserInfoMapper;
import com.java.pojo.bo.TransFlowBO;
import com.java.pojo.entity.Lend;
import com.java.pojo.entity.LendItem;
import com.java.mapper.LendItemMapper;
import com.java.pojo.entity.UserAccount;
import com.java.pojo.entity.UserInfo;
import com.java.pojo.vo.InvestVo;
import com.java.result.ResponseEnum;
import com.java.service.*;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.java.utils.LendNoUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * <p>
 * 标的出借记录表 服务实现类
 * </p>
 *
 * @author Helen
 * @since 2021-07-08
 */
@Service
public class LendItemServiceImpl extends ServiceImpl<LendItemMapper, LendItem> implements LendItemService {

    private static final Logger log1 = LoggerFactory.getLogger(LendItemServiceImpl.class);
    @Resource
    private UserInfoMapper userInfoMapper;

    @Resource
    private LendMapper lendMapper;

    @Resource
    private UserAccountMapper userAccountMapper;

    @Resource
    private UserBindService userBindService;

    @Resource
    private LendService lendService;

    @Resource
    private LendItemMapper lendItemMapper;

    @Resource
    private TransFlowService transFlowService;

    @Transactional(rollbackFor = Exception.class)
    @Override
    public String commitLendItem(InvestVo investVo) {
        //投资人id
        Long userId = investVo.getInvestUserId();
        Lend lend = lendMapper.selectById(investVo.getLendId());
        //校验当前的投资标的状态
        Assert.isTrue(lend.getStatus() == LendStatusEnum.INVEST_RUN.getStatus(), ResponseEnum.LEND_INVEST_ERROR);
        //当前已投金额 + 投资金额 > 标的金额
        BigDecimal investAmount = new BigDecimal(investVo.getInvestAmount());
        BigDecimal sum = lend.getInvestAmount().add(investAmount);
        Assert.isTrue(sum.doubleValue()<=lend.getAmount().doubleValue(),ResponseEnum.LEND_FULL_SCALE_ERROR);

        //校验余额判断
        QueryWrapper<UserAccount> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("user_id",userId);
        UserAccount userAccount = userAccountMapper.selectOne(queryWrapper);
        Assert.isTrue(userAccount.getAmount().doubleValue() > Double.parseDouble(investVo.getInvestAmount()),ResponseEnum.NOT_SUFFICIENT_FUNDS_ERROR);

        //投资人绑定协议号
        String bindCode = userBindService.getBindCodeByUserId(userId);
        //借款人绑定协议号
        String benefitBindCode = userBindService.getBindCodeByUserId(lend.getUserId());


        //在商户平台中生成投资信息==========================================
        //标的下的投资信息
        LendItem lendItem = new LendItem();
        lendItem.setInvestUserId(userId);//投资人id
        lendItem.setInvestName(investVo.getInvestName());//投资人名字
        String lendItemNo = LendNoUtils.getLendItemNo();
        lendItem.setLendItemNo(lendItemNo); //投资条目编号（一个Lend对应一个或多个LendItem）
        lendItem.setLendId(investVo.getLendId());//对应的标的id
        lendItem.setInvestAmount(new BigDecimal(investVo.getInvestAmount())); //此笔投资金额
        lendItem.setLendYearRate(lend.getLendYearRate());//年化
        lendItem.setInvestTime(LocalDateTime.now()); //投资时间
        lendItem.setLendStartDate(lend.getLendStartDate()); //开始时间
        lendItem.setLendEndDate(lend.getLendEndDate()); //结束时间
        //預期收益
        BigDecimal interestCount = lendService.getInterestCount(lendItem.getInvestAmount(), lendItem.getLendYearRate(), lend.getPeriod(), lend.getReturnMethod());
        lendItem.setExpectAmount(interestCount);
        lendItem.setRealAmount(new BigDecimal(0));
        lendItem.setStatus(0);
        lendItemMapper.insert(lendItem);

        //订单编号

        //将vo类数据取出封装为map
        Map<String, Object> paramMap = new HashMap<>();
        paramMap.put("agentId", HfbConst.AGENT_ID);
        paramMap.put("voteBindCode", bindCode);
        paramMap.put("benefitBindCode",benefitBindCode);
        paramMap.put("agentProjectCode", lend.getLendNo());//项目标号
        paramMap.put("agentProjectName", lend.getTitle());

        //在资金托管平台上的投资订单的唯一编号，要和lendItemNo保持一致。
        paramMap.put("agentBillNo", lendItemNo);//订单编号
        paramMap.put("voteAmt", investVo.getInvestAmount());//投资金额
        paramMap.put("votePrizeAmt", "0");
        paramMap.put("voteFeeAmt", "0");
        paramMap.put("projectAmt", lend.getAmount()); //标的总金额
        paramMap.put("note", "");
        paramMap.put("notifyUrl", HfbConst.INVEST_NOTIFY_URL); //检查常量是否正确
        paramMap.put("returnUrl", HfbConst.INVEST_RETURN_URL);
        paramMap.put("timestamp", RequestHelper.getTimestamp());
        String sign = RequestHelper.getSign(paramMap);
        paramMap.put("sign", sign);

        String form = FormHelper.buildForm(HfbConst.INVEST_URL, paramMap);
        return form;
    }

    //会员投资投之后的回调
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void Commitnotify(Map<String, Object> map) {
        //幂等性判断 根据交易流水是否存在
        String agentBillNo = (String)map.get("agentBillNo");
        Boolean saveTransFlow = transFlowService.isSaveTransFlow(agentBillNo);
        if(saveTransFlow){
            log1.info("幂等性返回");
        }
        //减少库存现金 增添冻结金额
        String voteBindCode = (String)map.get("voteBindCode");
        String voteAmt = (String)map.get("voteAmt");
        userInfoMapper.updateAmount(
                voteBindCode,
                new BigDecimal("-"+voteAmt),
                new BigDecimal(voteAmt)
        );
        LendItem lendItem =  this.getByLendItemNo(agentBillNo);
        //更新投资人数 金额
        lendItem.setStatus(1);//更新标的 1：已支付
        lendItemMapper.updateById(lendItem);
        Long lendId = lendItem.getLendId();
        Lend lend = lendMapper.selectById(lendId);
        lend.setInvestNum(lend.getInvestNum()+1);//新增一个投资人
        lend.setInvestAmount(lend.getInvestAmount().add(lendItem.getInvestAmount()));//增加投资金额
        lendMapper.updateById(lend);//更新标的的状态

        //新增交易流水
        TransFlowBO transFlowBO = new TransFlowBO(
                agentBillNo,
                voteBindCode,
                new BigDecimal(voteAmt),
                TransTypeEnum.INVEST_LOCK,
                "项目"+lend.getLendNo()+",项目名称："+lend.getTitle()
        );
        transFlowService.saveTransFlow(transFlowBO);
    }

    //获取当前标的下所有以支付的投资
    @Override
    public List<LendItem> selectByLendId(Long id, Integer i) {

        QueryWrapper<LendItem> wrapper = new QueryWrapper<>();
        wrapper.eq("status",i).eq("lend_id",id);
        return lendItemMapper.selectList(wrapper);
    }

    @Override
    public List<LendItem> getByLendId(Long lendId) {

        QueryWrapper<LendItem> wrapper = new QueryWrapper<>();
        wrapper.eq("lend_id",lendId);
        List<LendItem> lendItemList = lendItemMapper.selectList(wrapper);
        return lendItemList;
    }

    //通过编号查询lendItem
    private LendItem getByLendItemNo(String agentBillNo){
        QueryWrapper<LendItem> wrapper = new QueryWrapper<>();
        wrapper.eq("lend_item_no",agentBillNo);
        LendItem lendItem = lendItemMapper.selectOne(wrapper);
        return lendItem;
    }



}
